package rsvp.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


/**
 * 
 * This class contains all small but useful string transformations
 * 
 * @author Kuki Szabolcs 
 * @version (time) Jan 21, 2004 2:15:49 PM 
 */
public class StringUtilities {
	
	// System.getProperty("line.separator");
	/** new line characters */
	public static final String F_sNewLine = "\r\n";

	/**
	 * This methods replaces unwanted characters with space
	 * 
	 * @param value
	 * @return formated value
	 * @author Octavian.Ene
	 */
	public static String breakUpString(String value) {
		if (isNullOrEmpty(value))
			return value;
		else
			return value.replaceAll("->", " -> ").replaceAll("--", " - ")
					.replaceAll("-", " - ").replaceAll("_", " ");
	}

	/**
	 * This method will format string to HTML, for example new line into <br>
	 * 
	 * @param str
	 *            a String
	 * 
	 * @return a String
	 * 
	 */
	public static String formatStringToHtml(String str) {
		String s = "";

		if (str != null) {
			s = str.replaceAll("\r\n", "<br>");
			s = s.replaceAll("\n\r", "<br>");
			s = s.replaceAll("\r", "<br>");
			s = s.replaceAll("\n", "<br>");
			s = s.replaceAll("&", "&amp;");
		}
		return s;
	}

	/**
	 * This method will format Html to String
	 * 
	 * @param str
	 *            a String
	 * 
	 * @return a String
	 * 
	 */
	public static String formatHtmlToString(String str) {
		String s = "";

		if (str != null) {
			s = str.replaceAll("<br>", "\r\n");
		}

		return s;
	}

	/**
	 * check if the string is null or empty
	 * 
	 * @param strValue
	 * @return
	 * 
	 * @author Octavian Dumitras
	 * @version (time) Jul 6, 2004 2:00:23 PM
	 */
	public static boolean isNullOrEmpty(String strValue) {
		if (null == strValue || "".equals(strValue.trim()))
			return true;

		return false;
	}

	/**
	 * This is utility function when we need a variable number of spaces for
	 * example. <p/>
	 * 
	 * Sample: repeatToReachSize(" the ", 10) == " the the th"
	 * 
	 * @param baseString
	 * @param maxSize
	 * 
	 * @return
	 * 
	 */
	public static String repeatToReachSize(String baseString, int maxSize) {
		StringBuffer sb = new StringBuffer();
		while (sb.length() < maxSize)
			sb.append(baseString);
		sb.setLength(maxSize);
		return sb.toString();
	}


	
	/**
	 * This method will replace all characters &#287; with the corresponding
	 * unicode character
	 * 
	 * @param str
	 *            a String
	 * 
	 * @return a String
	 * @author Ionut @ 2003-05-25
	 */
	public static String replaceHtmlWithUnicodeChars(String str) {
		String sResult = str;
		String sCompute = "";
		String sRemaining = str;
		if (null == str || "".equals(str))
			return "";
		boolean changed = false;
		while (-1 != sRemaining.indexOf("&#")) {
			sCompute += sRemaining.substring(0, sRemaining.indexOf("&#"));
			sRemaining = sRemaining.substring(sRemaining.indexOf("&#"));
			if (-1 != sRemaining.indexOf(";")) {
				String strCode = sRemaining.substring(2, sRemaining
						.indexOf(";"));
				try {
					int code = Integer.parseInt(strCode);
					char c = (char) code;
					char[] ac = new char[1];
					ac[0] = c;
					sCompute += String.copyValueOf(ac);
					changed = true;
					if (sRemaining.indexOf(";") < sRemaining.length()) {
						// int ind = sRemaining.indexOf(";");
						String sR = sRemaining.substring(sRemaining
								.indexOf(";") + 1);
						sRemaining = sR;
					}
				} catch (Exception e) {
					// String ca =e.getMessage();
					sCompute += sRemaining;
				}
			} else {
				sCompute += sRemaining;
			}
			if (-1 == sRemaining.indexOf("&#")) {
				sCompute += sRemaining;
			}

		}
		if (changed)
			return sCompute;
		return sResult;
	}

	/**
	 * This method will replace all unicode characters with the code > 255) with
	 * the corresponding HTML characters in "&#nnn;" format unicode character
	 * 
	 * @param str
	 *            a String
	 * 
	 * @return a String
	 * @author Ionut @ 2003-05-26
	 */
	public static String replaceUnicodeWithHtmlChars(String str) {
		String sResult = "";
		// String sRemaining = str;
		if (null == str || "".equals(str))
			return "";

		int i = 0;
		while (i < str.length()) {
			int code = str.charAt(i);
			i++;
			if (code > 255) {
				sResult = sResult + "&#" + String.valueOf(code) + ";";
			} else {
				char c = (char) code;
				char[] ac = new char[1];
				ac[0] = c;
				sResult += String.copyValueOf(ac);
			}
		}
		return sResult;
	}

	/**
	 * Format a string for an Excel cell Format the new lines
	 * 
	 * @param s
	 * @return
	 */
	public static String toExcelText(String s) {
		if (s != null) {
			s = replaceAll(s, "\r\n", "\n");
			s = replaceAll(s, "\n\r", "\n");
		} else {
			s = "";
		}
		return s;
	}

	/**
	 * This method will format string to HTML, for example new line into <br>
	 * 
	 * @param s
	 * 
	 * @return a String
	 * 
	 */
	public static String toHTML(String s) {

		if (s != null) {
			s = replaceAll(s, "&", "&amp;");
			s = replaceAll(s, "<", "&lt;");
			s = replaceAll(s, ">", "&gt;");
			s = replaceAll(s, "\"", "&quot;");
			s = replaceAll(s, "'", "&#039;");

			s = replaceAll(s, "\r\n", "<br>");
			s = replaceAll(s, "\n\r", "<br>");
			s = replaceAll(s, "\r", "<br>");
			s = replaceAll(s, "\n", "<br>");
			s = replaceAll(s, "<br>", "<br>\n");
		} else {
			s = "";
		}
		return s;
	}

	/**
	 * This method will format string to HTML, for example new line into <br>
	 * 
	 * @param s
	 * 
	 * @return formated HTML
	 * 
	 */
	public static String toHTML_preaty(String s) {
		if (s != null) {
			// s = toHTML(s);

			s = replaceAll(s, "\r\n", "<br>");
			s = replaceAll(s, "\n\r", "<br>");
			s = replaceAll(s, "\r", "<br>");
			s = replaceAll(s, "\n", "<br>");
			s = replaceAll(s, "<br>", "<br>\n");
			s = replaceAll(s, " ", "&nbsp;");
		} else {
			s = "";
		}
		return s;
	}

	/**
	 * @param s
	 *            string to encode
	 * @return url encoded string
	 * 
	 * @author Kuki Szabolcs
	 * @version (time) Dec 3, 2003 12:03:37 PM
	 */
	public static String toURL(String s) {
		if (s != null) {
			s = replaceAll(s, " ", "%20");
		} else {
			s = "";
		}
		return s;
	}

	/**
	 * this method will escape string to SQL string. Example: "Kuki's cookbook"
	 * will be turned into "'Kuki''s cookbook'"
	 * 
	 * @param str
	 *            string to be transformed to SQL string
	 * 
	 * @return the SQL string
	 * 
	 * @author Kuki Szabolcs
	 * @version (time) Sep 19, 2003 8:03:43 PM
	 */
	public static String toSQL(String str) {
		String s = "";

		if (str == null)
			return "NULL";

		s = " '" + replaceAll(str, "'", "''") + "' ";

		return s;
	}

	/**
	 * return string ready formated for CSV
	 */
	public static String toCSVElement(String str) {
		String s = "";

		if (str == null)
			return "NULL";

		s = "\"" + replaceAll(str, "\"", "\"\"") + "\"";

		return s;
	}
	
	
	/**
	 * This method will transform date into an escaped string which SQL will
	 * recognize as date
	 * 
	 * @param dt
	 *            date to be transformed to SQL string
	 * 
	 * @return the SQL string
	 * 
	 * @author Kuki Szabolcs
	 * @version (time) Sep 19, 2003 8:03:43 PM
	 */
	public static String toSQL_dateOnly(Date dt) {
		String s = "";

		if (dt == null)
			return "NULL";

		s = " '" + new SimpleDateFormat("yyyy-MM-dd").format(dt) + "' ";

		return s;
	}

	/**
	 * This method will transforme date into an escaped string which SQL will
	 * recognize as date format 'YYYY-MM-DD hh:mi:ss'
	 * 
	 * @param dt
	 *            date to be transformed to SQL string
	 * 
	 * @return the SQL string
	 * 
	 * @author Kuki Szabolcs
	 * @version (time) Dec 1, 2003 1:47:59 PM
	 */
	public static String toSQL_datetime(Date dt) {
		String s = "";

		if (dt == null)
			return "NULL";

		s = " '" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(dt)
				+ "'  ";

		return s;
	}

	/**
	 * This method will format Html encoded string to partially decoded String
	 * 
	 * @param s
	 *            html encoded string
	 * 
	 * @return decoded string
	 */
	public static String html_to_string(String s) {

		if (s != null) {
			s = replaceAll(s, "<br>", "\r\n");
			s = replaceAll(s, "&amp;", "&");
			s = replaceAll(s, "&lt;", "<");
			s = replaceAll(s, "&gt;", ">");
			s = replaceAll(s, "&quot;", "\"");
			s = replaceAll(s, "&#039;", "'");
		}

		return s;
	}

	/**
	 * This is utility function adds leading zeros to the string repsentation of
	 * an integer value <p/>
	 * 
	 * Sample: padWithZero(2, 2) == "02"
	 * 
	 * @param nIntValue
	 * @param nMaxSize
	 *            value max size of resulted string
	 * 
	 * @return a String
	 * @author Romana 2003-12-10
	 * 
	 */
	public static String padWithZero(int nIntValue, int nMaxSize) {
		StringBuffer sb = new StringBuffer(Integer.toString(nIntValue));
		while (sb.length() < nMaxSize)
			sb.insert(0, '0');
		sb.setLength(nMaxSize);
		return sb.toString();
	}

	/**
	 * Check if the email address is valid or not.
	 * 
	 * @param sEmail
	 *            a String
	 * 
	 * @return a boolean
	 * 
	 */
	public static boolean isValidEmail(String sEmail) {
		if (sEmail == null)
			return false;
		int indexMonkey = sEmail.indexOf("@");
		if (1 > indexMonkey)
			return false;
		int indexDotAfterMonkey = sEmail.indexOf(".", indexMonkey + 1);
		if (0 > indexDotAfterMonkey)
			return false;
		if (sEmail.length() == (indexDotAfterMonkey + 1))
			return false;

		// every condition is ok
		return true;
	}

	
	
	/**
	 * Check if a string contains only alphanumeric or underline characters
	 * 
	 * @param strCheck
	 *            a String
	 * @return a boolean
	 * 
	 * @author Ionut
	 */
	public static boolean isAlphanumericalString(String strCheck) {
		String strProcess = null;
		int intPos = 0;
		char cChr = 0;
		if (null == strCheck || "".equalsIgnoreCase(strCheck.trim()))
			return false;

		strProcess = strCheck.trim();
		cChr = strProcess.charAt(intPos);

		// alphanumeric or underline characters are allowed
		while ((Character.isLetterOrDigit(cChr) || cChr == '_')
				&& (intPos < strProcess.length())) {
			intPos++;
			if (intPos < strProcess.length())
				cChr = strProcess.charAt(intPos);
		}

		if (intPos < strProcess.length())
			return false;
		return true;
	}

	/**
	 * replace all implementation for JDK backward compatibility
	 * 
	 * @param strText
	 * @param strLookFor
	 * @param strReplaceWith
	 * 
	 * @return new text with the replaced elements completed
	 * 
	 * @author Kuki Szabolcs
	 * @version (time) Sep 29, 2003 3:58:00 PM
	 */
	public static String replaceAll(String strText, String strLookFor,
			String strReplaceWith) {
		String sbRest = strText;
		String sResult = "";
		while (true) {
			int idx = sbRest.indexOf(strLookFor);
			if (idx < 0) {
				break;
			}
			sResult += sbRest.substring(0, idx) + strReplaceWith;
			sbRest = sbRest.substring(idx + strLookFor.length());
		}
		sResult += sbRest;
		return sResult;
	}

	/**
	 * read up (skip) (line by line) all information until end place holder is
	 * met
	 * 
	 * @param reader
	 *            source to read from
	 * @param sEndPlaceHolder
	 *            search in last line (if found stop)
	 * 
	 * @return last line readed
	 * @throws IOException
	 * 
	 * @author Kuki Szabolcs (kuki@berg-computers.com)
	 * @version (time) Oct 17, 2003 2:21:25 PM
	 */
	public static String skipTo(BufferedReader reader, String sEndPlaceHolder)
			throws IOException {
		String sCurrentLine;
		while ((sCurrentLine = reader.readLine()) != null) {
			if (sCurrentLine.indexOf(sEndPlaceHolder) != -1) {
				break;
			}
		}
		return sCurrentLine;
	}

	/**
	 * convert string to HTML but return a certain string if string to be
	 * converted is null
	 * 
	 * @param sInput
	 * @param sDefault
	 * 
	 * @author Romana 2003-12-10
	 * 
	 * @return converted string
	 */
	public static String toHTML_withDefault(String sInput, String sDefault) {
		if (null == sInput) {
			return sDefault;
		}
		return toHTML(sInput);
	}

	/**
	 * @param sComplete
	 * @param iLeftIndex
	 * 
	 * @return sComplete or if is bigger then iLeftIndex then return only the
	 *         first iLeftIndex of sComplete
	 * 
	 * @author Kuki Szabolcs
	 * @version (time) Dec 12, 2003 3:03:56 PM
	 */
	public static String left(String sComplete, int iLeftIndex) {
		String sRet = sComplete;
		if (sComplete.length() > iLeftIndex)
			sRet = sComplete.substring(0, iLeftIndex);

		return sRet;
	}

	/**
	 * convert the string to int and return the value. if the conversion failed =>
	 * return default value
	 * 
	 * @param strNumber
	 * @param iDefaultValue
	 * @return
	 * @author Octavian Dumitras
	 * @version (time) Jan 28, 2004 1:53:03 PM
	 */
	public static int parseInt(String strNumber, int iDefaultValue) {
		if (null == strNumber) {
			return iDefaultValue;
		}

		int iReturnValue = 0;
		try {
			iReturnValue = Integer.parseInt(strNumber);
		} catch (NumberFormatException e) {
			iReturnValue = iDefaultValue;
		}

		return iReturnValue;
	}

	/**
	 * convert the string to double and return the value. if the conversion
	 * failed => return default value
	 * 
	 * @param strNumber
	 * @param dDefaultValue
	 * @return
	 * @author Octavian Dumitras
	 * @version (time) Jan 28, 2004 1:53:03 PM
	 */
	public static double parseDouble(String strNumber, double dDefaultValue) {
		if (null == strNumber) {
			return dDefaultValue;
		}

		double dReturnValue = 0;
		try {
			dReturnValue = Double.parseDouble(strNumber);
		} catch (NumberFormatException e) {
			dReturnValue = dDefaultValue;
		}

		return dReturnValue;
	}

	/**
	 * Method getURLEncode
	 * 
	 * @param strText
	 *            a String
	 * 
	 * @return a String
	 * @throws UnsupportedEncodingException
	 * 
	 */
	public static String getURLEncode(String strText)
			throws UnsupportedEncodingException {
		return URLEncoder.encode(strText, "UTF-8");
	}

	/**
	 * This method will transform date into an escaped string which Oracle9 SQL
	 * will recognize as date
	 * 
	 * @param dt
	 *            date to be transformed to SQL string
	 * 
	 * @return the SQL string
	 * 
	 * @author Kuki Szabolcs
	 * @version (time) Feb 13, 2004 4:33:43 PM
	 */
	public static String toSQL_dateOnly_Oracle9(Date dt) {
		String s = "";

		if (dt == null)
			return "NULL";

		s = " TO_Date('" + new SimpleDateFormat("yyyy-MM-dd").format(dt)
				+ "', 'YYYY-MM-DD') ";

		return s;
	}

	/**
	 * example: if string is "xyz" => "Xyz" and if string is "XYz" => "Xyz"
	 * 
	 * @param str
	 * @return first caracter capitalized and rest of the string with lower case
	 * @author Kuki
	 * @version 2004-02-24
	 */
	public static String capitalize(String str) {
		if (str.length() == 0)
			return str;
		String s1 = str.substring(0, 1).toUpperCase();
		if (str.length() == 1)
			return s1;
		String s2 = str.substring(1).toLowerCase();
		return s1 + s2;
	}

	/**
	 * @param str
	 *            fraze to be capitalized
	 * @return example: "This fraze will be capitalized" => "This Fraze Will Be
	 *         Capitalized"
	 * 
	 * @author Kuki
	 * @version 2004-02-24
	 */
	public static String capitalizeAllWords(String str) {
		StringTokenizer st = new StringTokenizer(str, " ");
		String strReturn = "";
		boolean bFirst = true;
		while (st.hasMoreTokens()) {
			if (bFirst) {
				bFirst = false;
			} else {
				strReturn += " ";
			}
			strReturn += capitalize(st.nextToken());
		}

		return strReturn;
	}

	/**
	 * @param updatedDescription
	 * @return string escaped for XML replace " with &quote; etc...
	 */
	public static String toXML(String updatedDescription) {
		String sResult = updatedDescription.replaceAll("\"", "&quot;");
		sResult = sResult.replaceAll("<", "&lt;");
		sResult = sResult.replaceAll(">", "&gt;");
		return sResult;
	}
	
	/**
	 * @param sdata
	 *            extract the new CSV value, note this value will change, 
	 *            the value extracted will be subtracted from this variable
	 * 
	 * 
	 * @return the new CSV value
	 */
	public static String readCSVLine_extractNextCSV_value(StringBuffer sdata) {

		if (0 == sdata.length())
			return null;

		boolean bEndWithQuotes = sdata.charAt(0) == '"';
		if (bEndWithQuotes)
			sdata.delete(0, 1);
		String sSearchForDelimiter = bEndWithQuotes ? "\"," : ",";
		int iSearchDelimiterLenght = sSearchForDelimiter.length();
		int iFoundNextDelimiter = sdata.indexOf(sSearchForDelimiter);
		if (-1 == iFoundNextDelimiter)
			iFoundNextDelimiter = bEndWithQuotes ? sdata.length() - 1 : sdata
					.length();

		String sNewString = sdata.substring(0, iFoundNextDelimiter);
		sdata.delete(0, iFoundNextDelimiter + iSearchDelimiterLenght);
		sNewString = sNewString.replaceAll("\\\"", "\"\"");

		return sNewString;
	}
	
	

	/**
	 * @param regex
	 * @param sInput
	 * 
	 * @return the first group matched 
	 * 
	 * 
	 * input:   abbc
	 * pattern: a(b*)c
	 * returns:  bb
	 */
	public static String regex_getFirstGroupMatch(String regex, String sInput) {

		// Compile and use regular expression
		Pattern pattern = Pattern.compile(regex);
		Matcher matcher = pattern.matcher(sInput);
		boolean matchFound = matcher.find();

		if (matchFound) {
			// Get all groups for this match
			int iGroupCount = matcher.groupCount();
		
			for (int i2 = 1; i2 <= iGroupCount; /* i2++ */) {				
				return matcher.group(i2);
			}
		}
		
		return null;
	}

	
	
	
	
	/**
	 * @param sSource
	 * @param sDelimiter
	 * 
	 * @return part of source until sDelimiter is reached.
	 */
	public static String extractStringUntilDelimiter(String sSource, String sDelimiter) {

		int ip = sSource.indexOf(sDelimiter);
		if (-1 == ip)
			return sSource;
		
		return sSource.substring(0, ip);
	}
}
